#!/bin/bash

# DRAFT
#
# script to run regression (and other) tests on Elda.
#
# running `alchemy run INSTANCES=wherever will search
# under `whatever` for test suites. A suit is identified
# by containing a file `model.ttl`. Each such suite
# also contains an LDA config in `config.ttl` and tests in 
# directories named `test_*`. Each such directory contains a 
# file `uri.get` whose content is the URI to pass to Elda 
# with the leading http://localhost:somePort/someAPP removed.
#
# outputs from the test are written to a work directory
# to files under the same name as the name of the suite.
#
# If there is no file named `status` in the work directory,
# the query is passed to Elda and the reponse code is
# witten into `status`, the content type into `content-type`,
# and the content into `gold`.
#
# If there is such a file, then the content is compared with
# `gold`. If it is "the same" (for specified values of "same")
# then the (non-) differences are written into OK and any
# file PROBLEM deleted. Otherwise any file OK is deleted and
# the (real) differences written into PROBLEM.
#
# Hence one mode of operation is to run the tests using
# a "correct" version of Elda first (to establish gold) and
# then again with a different (eg newer) Elda to see if
# any unexpected differences have appeared.
#
# The model.ttl files are not expected to be large: Elda reads
# them into a memory model and queries that model. The config
# file must specify the SPARQL endpoint appropriately:
#    
#	api:sparqlEndpoint <local:../model.ttl>
#
# The `..` allows for the running Elda's current directory
# being a temporary sub-directory of the test directory.
#
# When the tests have been run, the running Elda is shut
# down and its working directory deleted.
#

function setup() {
	# establish clean local copies 
	rm -rf standalone*; cp -r $_STANDALONE standalone.jar
}

function init-tests() {
	for t in $_INSTANCES/*; do
		echo cleaning $t
		(cd $t; \
			rm -rf .standalone-log ; \
			for x in test_*; do \
				(cd $x; rm -f OUTPUT gold .response_status status content-type OK PROBLEM) ; \
			done \
		)
	done
}

function run-tests() {
	export ALCHEMY=$PWD
	echo instances: $_INSTANCES
	for t in $_INSTANCES; do
		for m in $(find $t -name model.ttl); do
			export instance_path=$(dirname $(realpath -m $m))
			export instance_name=$(basename $instance_path)
			export work_path=$_WORKDIR/$instance_name
			export standalone=$(cd $ALCHEMY; realpath -m $_STANDALONE)
		#
			echo instance $instance_path results in $work_path
			echo standalone is $standalone
			mkdir -p $work_path
		#
			pushd $work_path > /dev/null
		#
			unzip -o -q $standalone -d standalone
		#
			ln -s -f $instance_path/model.ttl model.ttl
		#
			(cd standalone; \
				java -jar start.jar \
					-Delda.spec=$instance_path/config.ttl \
					2> ../standalone-log \
				& echo $! > ../standalone-pid \
			)
			sleep 10
		#
			export cp=$(echo $PWD/standalone/webapps/standalone/WEB-INF/lib/* | sed -e 's/ /:/g')
		#
			for x in $instance_path/test_*; do
				mkdir -p $(basename $x)
				pushd $(basename $x) > /dev/null
				# content-type gold OK/PROBLEM status uri.get
				# uri.get is the provided part
				curl -o OUTPUT \
					-w "__STATUS=%{response_code}\n__TYPE=%{content_type}\n" \
					> response_status 2> /dev/null \
					http://localhost:8080/standalone/$(cat $x/uri.get)
			#
				rm -f failed_queries
				if test -n "$(find $x -name '*.rq' -print -quit)"; then
					cp OUTPUT OUTPUT.ttl
					for q in $x/*.rq; do
						export maybe=$(basename $q | sed -e 's/^.*\(Yes\|No\).rq/\1/')
						export answer=$(java -classpath $cp arq.sparql --query $q --data OUTPUT.ttl)
					#
						if [[ "$answer" != "Ask => $maybe" ]]; then
							echo FAILED: $q
							echo $q >> failed_queries
						fi
					done
					rm OUTPUT.ttl
				fi
			#
				source response_status
				if [ -e status ]; then
					# initialised
					if diff OUTPUT gold > differences ; then
						rm -f PROBLEM
						mv differences OK
					else
						rm -f OK
						mv differences PROBLEM
						echo -e "\n" problem with $t/$x URI=$(cat $x/uri.get) "\n"
					fi
				else
					# this is the 'first' time
					echo $__STATUS > status
					echo $__TYPE | sed -e 's:/:_:' > content-type
					mv OUTPUT gold
				fi
			#
				popd > /dev/null
			done
		#
			kill $(cat standalone-pid)
			# rm -rf standalone standalone-pid
			popd > /dev/null
		done
	done
}


if [ "$*" == "" ]; then
	echo alchemy COMMAND
	echo COMMAND ::= setup / init / run
else
	# default settings
	export _INSTANCES=./elda-alchemy-tests/instances
	export _STANDALONE=./elda-standalone/target/elda-standalone-1.2.24.jar
	export _WORKDIR=./work

	if [ -e ~/.alchemy ]; then source ~/.alchemy; fi
	if [ -e .alchemy  ]; then source .alchemy; fi

	# absorb commands
	export command=$1; shift; for x in $*; do export _$x; done

	# execute command
	case $command in
		setup) setup ;;
		clean) init-tests ;;
		run) run-tests ;;
		exp) experiment ;;
		*) echo I don"'"t know how to do "'"$command"'".
	esac
fi


